using System.Collections.Generic;
using System.Text;

namespace CombatTracker.Creatures
{
  public class InitiativeList : LinkedList<Creature>
  {
    private Creature _currentTurn;
    private int _currentRound;

    public event TurnChangedEvent TurnAdvanced;
    public event TurnChangedEvent RoundAdvanced;
    public event InitiativeListEvent ListChanged;

    public Creature CurrentTurn
    {
      get { return _currentTurn; }
      private set
      {
        Creature previousTurn = _currentTurn;
        _currentTurn = value;
        if (TurnAdvanced != null)
        {
          if (previousTurn != null) previousTurn.EndTurn();
          TurnAdvanced(this, previousTurn);
          _currentTurn.StartTurn();
        }
      }
    }

    public int CurrentRound
    {
      set
      {
        _currentRound = value;
        if (RoundAdvanced != null)
        {
          RoundAdvanced(this, Last.Value);
        }
      }
      get { return _currentRound; }
    }

    public void StartCombat()
    {
      CurrentTurn = First.Value;
      CurrentRound = 1;
    }

    public void NextTurn()
    {
      if (Find(CurrentTurn) != null && Find(CurrentTurn).Next != null)
      {
        CurrentTurn = Find(CurrentTurn).Next.Value;
      }
      else
      {
        CurrentTurn = First.Value;
        CurrentRound += 1;
      }
    }

    public override string ToString()
    {
      StringBuilder result = new StringBuilder();
      foreach (Creature creature in this)
      {
        result.AppendLine(creature.Name + ": " + creature.InitiativeRoll + " / " + creature.InitiativeBonus);
      }

      return result.ToString();
    }

    public void SetInitiativeStateListener(InitiativeStateEvent listener)
    {
      foreach (Creature creature in this)
      {
        creature.InitiativeStateChanged += listener;
      }
    }

    public void SetStartOfTurnListener(CreatureEvent listener)
    {
      foreach (Creature creature in this)
      {
        creature.StartOfTurn += listener;
      }
    }

    public void SetEndOfTurnListener(CreatureEvent listener)
    {
      foreach (Creature creature in this)
      {
        creature.EndOfTurn += listener;
      }
    }

    private void OnListChanged()
    {
      if (ListChanged != null)
      {
        ListChanged(this);
      }
    }

    #region ListChanged Shadow Functions

    public new void AddAfter(LinkedListNode<Creature> node, Creature value)
    {
      base.AddAfter(node, value);
      OnListChanged();
    }

    public new void AddAfter(LinkedListNode<Creature> node, LinkedListNode<Creature> newNode)
    {
      base.AddAfter(node, newNode);
      OnListChanged();
    }

    public new void AddBefore(LinkedListNode<Creature> node, Creature value)
    {
      base.AddBefore(node, value);
      OnListChanged();
    }

    public new void AddBefore(LinkedListNode<Creature> node, LinkedListNode<Creature> newNode)
    {
      base.AddBefore(node, newNode);
      OnListChanged();
    }

    public new void AddFirst(Creature value)
    {
      base.AddFirst(value);
      OnListChanged();
    }

    public new void AddFirst(LinkedListNode<Creature> node)
    {
      base.AddFirst(node);
      OnListChanged();
    }

    public new void AddLast(Creature value)
    {
      base.AddLast(value);
      OnListChanged();
    }

    public new void AddLast(LinkedListNode<Creature> node)
    {
      base.AddLast(node);
      OnListChanged();
    }

    public new void Clear()
    {
      base.Clear();
      OnListChanged();
    }

    public new void Remove(Creature value)
    {
      base.Remove(value);
      OnListChanged();
    }

    public new void Remove(LinkedListNode<Creature> node)
    {
      base.Remove(node);
      OnListChanged();
    }

    public new void RemoveFirst()
    {
      base.RemoveFirst();
      OnListChanged();
    }

    public new void RemoveLast()
    {
      base.RemoveLast();
      OnListChanged();
    }

    #endregion
  }

  public delegate void TurnChangedEvent(InitiativeList sender, Creature previousTurn);

  public delegate void InitiativeListEvent(InitiativeList sender);
}